//
//  SandboxStorage.swift
//  ADKit
//
//  Created by Adoma on 2024/10/17.
//

import SwiftyJSON
import Cache

/// by ADKit
public class SandboxStorage: DataStorageType {

    let storage: Storage<String, Data>?
    
    private lazy var jsonStorage = storage?.transformCodable(ofType: JSON.self)
    private lazy var stringStorage = storage?.transformCodable(ofType: String.self)

    public convenience init(name: String) {

        let documentDirectory = try? FileManager.default.url(for: .documentDirectory,
                                                     in: .userDomainMask,
                                                     appropriateFor: nil, create: true)
        
        let directory = documentDirectory?.appendingPathComponent(Bundle.main.name)
        
        self.init(directory: directory, name: name)
    }
    
    public init(directory: URL?, name: String) {
        
        let disk = DiskConfig(name: name, directory: directory)
        let memory = MemoryConfig()
        let transformer = TransformerFactory.forData()
        
        self.storage = try? Storage(diskConfig: disk,
                                    memoryConfig: memory,
                                    transformer: transformer)
    }
    
    // MARK: JSON
    public func set(json: JSON?, for key: Key)  {
        guard let object = json else {
            remove(key: key)
            return
        }
        try? jsonStorage?.setObject(object, forKey: key)
    }
    
    public func json(for key: Key)  -> JSON? {
        return try? jsonStorage?.object(forKey: key)
    }
    
    // MARK: String
    public func set(string: String?, for key: Key)  {
        guard let object = string else {
            remove(key: key)
            return
        }
        try? stringStorage?.setObject(object, forKey: key)
    }
    
    public func string(for key: Key)  -> String? {
        return try? stringStorage?.object(forKey: key)
    }
    
    // MARK: Data
    public func set(data: Data?, for key: Key)  {
        guard let object = data else {
            remove(key: key)
            return
        }
        try? storage?.setObject(object, forKey: key)
    }
    
    public func data(for key: Key)  -> Data? {
        try? storage?.object(forKey: key)
    }

    public func remove(key: Key)  {
        try? storage?.removeObject(forKey: key)
    }

    public func clean()  {
        try? storage?.removeAll()
    }
    
}
